package com.googlecode.connectlet.crypto.rsa.provider;

import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureSpi;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;

import com.googlecode.connectlet.crypto.digest.SignatureStream;

public abstract class RSASignature extends SignatureSpi {
	private SignatureStream stream = null;

	protected abstract SignatureStream getSignStream(RSAPrivateCrtKey privateKey);
	protected abstract SignatureStream getVerifyStream(RSAPublicKey publicKey);

	@Override
	protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
		if (privateKey instanceof RSAPrivateCrtKey) {
			stream = getSignStream((RSAPrivateCrtKey) privateKey);
		} else {
			throw new InvalidKeyException();
		}
	}

	@Override
	protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
		if (publicKey instanceof RSAPublicKey) {
			stream = getVerifyStream((RSAPublicKey) publicKey);
		} else {
			throw new InvalidKeyException();
		}
	}

	@Override
	protected void engineUpdate(byte b) {
		stream.write(b);
	}

	@Override
	protected void engineUpdate(byte[] b, int off, int len) {
		stream.write(b, off, len);
	}

	@Override
	protected byte[] engineSign() {
		byte[] result = stream.sign();
		stream.reset();
		return result;
	}

	@Override
	protected boolean engineVerify(byte[] sigBytes) {
		boolean result = stream.verify(sigBytes);
		stream.reset();
		return result;
	}

	@Deprecated
	@Override
	protected Object engineGetParameter(String param) {
		throw new UnsupportedOperationException();
	}

	@Deprecated
	@Override
	protected void engineSetParameter(String param, Object value) {
		throw new UnsupportedOperationException();
	}
}